package model;

import java.util.ArrayList;

import org.jblas.DoubleMatrix;

import util.Params;

/**
 * Max function layer of the network.
 * 
 * 神经网络的最大值函数层。
 * 
 * @author Tianyu Xu
 * 
 */
public class MaxFuncLayer {
	private static ArrayList<int[]> maxIndex = null;

	public static ArrayList<int[]> getMaxIndex() {
		return maxIndex;
	}

	/**
	 * 获取一个行向量的最大值，同时储存取得该最大值时的列索引。
	 * 
	 * @param rowNum
	 *            行向量的行索引
	 * @param wordIndex
	 *            该行向量属于哪一个字符的输出矩阵
	 * @param rowVector
	 *            要寻找最大值的行向量
	 * @return
	 */
	private static double getMax(int rowNum, int wordIndex, DoubleMatrix rowVector) {
		double max = -Double.MAX_VALUE;
		int[] maxIndexArr = maxIndex.get(wordIndex);
		maxIndexArr[rowNum] = -1;

		for (int c = 0; c < rowVector.columns; c++) {
			if (max < rowVector.get(c)) {
				max = rowVector.get(c);
				maxIndexArr[rowNum] = c;
			}
		}
		return max;
	}

	/**
	 * 给定第 wordIndex 个字的卷积网络输出矩阵，找到每行的最大值并保存取到最大值时的列数
	 * 
	 * @param inputMatrix
	 *            第 wordIndex 个字的卷积网络输出矩阵
	 * @param wordIndex
	 *            句子中的字符编号（不含左右padding）
	 * @return 保存了每行的最大值的列向量
	 */
	public DoubleMatrix performMaxTrans(DoubleMatrix inputMatrix, int wordIndex) {
		DoubleMatrix output = new DoubleMatrix(Params.CONVOLITION_LAYER_SIZE);
		for (int r = 0; r < Params.CONVOLITION_LAYER_SIZE; r++) {
			output.put(r, getMax(r, wordIndex, inputMatrix.getRow(r)));
		}
		return output;
	}

	/**
	 * 重置最大值序号列表，开始处理一个新的句子。
	 * 
	 * @param length
	 *            新句子的长度（不含 paddings）
	 */
	public void startNewSentence(int length) {
		maxIndex = new ArrayList<int[]>(length);
		for (int i = 0; i < length; i++) {
			maxIndex.add(new int[Params.CONVOLITION_LAYER_SIZE]);
		}
	}
}
